using System.Globalization;
using System.Text.Json;

namespace Journal.Core.Services.Logging;

public sealed class CommandLogger
{
    public static void LogStart(string action, string correlationId, JsonElement? payload)
    {
        var redactedPayload = LogRedactor.RedactPayload(payload);
        EmitLog("information", action, correlationId, "start", redactedPayload);
    }

    public static void LogSuccess(string action, string correlationId) => EmitLog("information", action, correlationId, "success");

    public static void LogFailure(string action, string correlationId, string errorType, string? message = null)
    {
        var details = string.IsNullOrWhiteSpace(message)
            ? ""
            : (message!.Length <= 160 ? message : $"{message[..160]}...(truncated)");
        EmitLog("warning", action, correlationId, "failure", errorType: errorType, details: details);
    }

    private static void EmitLog(
        string level,
        string action,
        string correlationId,
        string outcome,
        object? payload = null,
        string? errorType = null,
        string? details = null)
    {
        if (!ShouldLog(level))
            return;

        var envelope = new
        {
            timestamp = DateTime.UtcNow.ToString("O", CultureInfo.InvariantCulture),
            level,
            component = "Entry",
            action,
            correlation_id = correlationId,
            outcome,
            error_type = errorType,
            details,
            payload
        };
        Console.Error.WriteLine(JsonSerializer.Serialize(envelope));
    }

    private static bool ShouldLog(string level)
    {
        var configured = (Environment.GetEnvironmentVariable("JOURNAL_LOG_LEVEL") ?? "warning")
            .Trim()
            .ToLowerInvariant();
        var configuredRank = LogLevelRank(configured);
        var incomingRank = LogLevelRank(level);
        return incomingRank >= configuredRank;
    }

    private static int LogLevelRank(string level) => level switch
    {
        "trace" => 0,
        "debug" => 1,
        "information" => 2,
        "info" => 2,
        "warning" => 3,
        "warn" => 3,
        "error" => 4,
        "critical" => 5,
        _ => 3
    };
}
