using System.Data;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Enrichers.Span;
using Serilog.Events;
using Serilog.Exceptions;
using Serilog.Formatting.Json;
using Serilog.Sinks.MSSqlServer;

namespace Baya.Infrastructure.CrossCutting.Logging;

public static class LoggingConfiguration
{
    public static Action<HostBuilderContext, LoggerConfiguration> ConfigureLogger => (context, configuration) =>
    {
        #region Level & enrichment

        var env = context.HostingEnvironment;

        // refinement-phase-9 §9.3: deployed environments log Information+ (previously Warning+, which silently
        // dropped every Information-level audit trail — logins, money-operation context). Framework categories
        // are held at Warning so raising the floor doesn't flood the sink with ASP.NET/EF request noise.
        // No PII/secrets are ever logged: the mock SMS sender no longer logs the OTP code, and clinical text /
        // IBANs / phone numbers are encrypted or masked before they reach any handler that logs.
        configuration
            .MinimumLevel.Information()
            .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.WithProperty("ApplicationName", env.ApplicationName)
            .Enrich.WithProperty("Environment", env.EnvironmentName)
            .Enrich.WithSpan()
            .Enrich.WithExceptionDetails();

        #endregion

        var columnOpts = new ColumnOptions();
        columnOpts.Store.Remove(StandardColumn.Properties);
        columnOpts.Store.Add(StandardColumn.LogEvent);
        columnOpts.LogEvent.DataLength = 4096;
        columnOpts.PrimaryKey = columnOpts.Id;
        columnOpts.Id.DataType = SqlDbType.Int;

        // Development and Testing (WebApplicationFactory) log locally; the SQL sink is for deployed envs.
        if (!context.HostingEnvironment.IsDevelopment() && !context.HostingEnvironment.IsEnvironment("Testing"))
        {
            // Retention for the `log.LogEvents` table is an ops/DBA responsibility (a scheduled purge or a
            // partitioned/rolling table on Baya_Logs) — distinct from application data. Set an OpenTelemetry:Otlp
            // collector (see OpenTelemetryConfigurations) if you prefer to ship logs off-box instead of the SQL sink.
            configuration.WriteTo
                .MSSqlServer(
                    connectionString: context.Configuration.GetConnectionString("logDb"),
                    sinkOptions: new MSSqlServerSinkOptions { TableName = "LogEvents", AutoCreateSqlTable = true, SchemaName = "log", AutoCreateSqlDatabase = true },
                    columnOptions: columnOpts);
        }
        else
        {
            configuration.WriteTo.Console();
            configuration.WriteTo.File(new JsonFormatter(), "logs/log.json");
        }
    };
}
