using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using MyNewProjectName.Infrastructure.Options;
using Serilog;
using Serilog.Events;
using Serilog.Formatting.Compact;

namespace MyNewProjectName.Infrastructure.Extensions;

/// <summary>
/// Extension methods for configuring Serilog
/// </summary>
public static class SerilogExtensions
{
    /// <summary>
    /// Configure Serilog with structured JSON logging
    /// </summary>
    public static IHostBuilder UseSerilogLogging(this IHostBuilder hostBuilder, IConfiguration configuration)
    {
        var serilogOptions = configuration.GetSection(SerilogOptions.SectionName).Get<SerilogOptions>() 
            ?? new SerilogOptions();

        var loggerConfiguration = new LoggerConfiguration()
            .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
            .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
            .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning)
            .MinimumLevel.Override("System", LogEventLevel.Warning)
            .Enrich.FromLogContext()
            .Enrich.WithEnvironmentName()
            .Enrich.WithMachineName()
            .Enrich.WithThreadId()
            .Enrich.WithProperty("Application", "MyNewProjectName");

        // Set minimum level from configuration
        if (Enum.TryParse<LogEventLevel>(serilogOptions.MinimumLevel, out var minLevel))
        {
            loggerConfiguration.MinimumLevel.Is(minLevel);
        }

        // Apply overrides from configuration
        foreach (var overrideConfig in serilogOptions.Override)
        {
            if (Enum.TryParse<LogEventLevel>(overrideConfig.Value, out var overrideLevel))
            {
                loggerConfiguration.MinimumLevel.Override(overrideConfig.Key, overrideLevel);
            }
        }

        // Console sink with JSON formatting (Compact JSON format)
        if (serilogOptions.WriteToConsole)
        {
            loggerConfiguration.WriteTo.Console(new CompactJsonFormatter());
        }

        // File sink with rolling
        if (serilogOptions.WriteToFile)
        {
            var rollingInterval = Enum.TryParse<RollingInterval>(serilogOptions.RollingInterval, out var interval)
                ? interval
                : RollingInterval.Day;

            loggerConfiguration.WriteTo.File(
                new CompactJsonFormatter(),
                serilogOptions.FilePath,
                rollingInterval: rollingInterval,
                retainedFileCountLimit: serilogOptions.RetainedFileCountLimit,
                shared: true);
        }

        // Seq sink (optional)
        if (!string.IsNullOrWhiteSpace(serilogOptions.SeqUrl))
        {
            loggerConfiguration.WriteTo.Seq(serilogOptions.SeqUrl);
        }

        // Elasticsearch sink (optional)
        if (!string.IsNullOrWhiteSpace(serilogOptions.ElasticsearchUrl))
        {
            // Note: Add Serilog.Sinks.Elasticsearch package if needed
            // loggerConfiguration.WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri(serilogOptions.ElasticsearchUrl)));
        }

        Log.Logger = loggerConfiguration.CreateLogger();

        return hostBuilder.UseSerilog();
    }
}
