using Application.Extensions;
using Infrastructure.Extensions;
using Microsoft.OpenApi.Models;
using System.Reflection;
using WebApi.Configuration;
using WebApi.Middleware;
using Serilog;

// Configure Serilog early for startup logging
SerilogConfiguration.CreateBootstrapLogger();

try
{
    Log.Information("Starting web application");

    var builder = WebApplication.CreateBuilder(args);

    // Configure Serilog
    SerilogConfiguration.ConfigureSerilog(builder);

    // Add layer services using extension methods
    builder.Services.AddInfrastructure(builder.Configuration);
    builder.Services.AddApplication();

    // Add framework services
    builder.Services.AddControllers();
    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo 
        { 
            Title = "Generated API", 
            Version = "v1",
            Description = "Auto-generated Clean Architecture API from PostgreSQL schema"
        });
        
        // Include XML comments if available
        var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
        var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
        if (File.Exists(xmlPath))
        {
            c.IncludeXmlComments(xmlPath);
        }
    });

    var app = builder.Build();

    // Configure Serilog request logging
    app.UseSerilogRequestLogging(options =>
    {
        options.MessageTemplate = "HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000}ms";
        options.GetLevel = (httpContext, elapsed, ex) => ex != null 
            ? Serilog.Events.LogEventLevel.Error 
            : httpContext.Response.StatusCode > 499 
                ? Serilog.Events.LogEventLevel.Error
                : Serilog.Events.LogEventLevel.Information;
        options.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
        {
            var requestHost = httpContext.Request.Host.HasValue ? httpContext.Request.Host.ToString() : string.Empty;
            var requestScheme = httpContext.Request.Scheme ?? string.Empty;
            var remoteIp = httpContext.Connection.RemoteIpAddress?.ToString() ?? string.Empty;

            diagnosticContext.Set("RequestHost", requestHost);
            diagnosticContext.Set("RequestScheme", requestScheme);
            diagnosticContext.Set("RemoteIpAddress", remoteIp);
        };
    });

    // Add correlation ID middleware (must be early in pipeline)
    app.UseCorrelationId();

    // Optional: use one logging approach to avoid duplicate logs
    // app.UseRequestLogging();

    // Configure the HTTP request pipeline
    if (app.Environment.IsDevelopment())
    {
        app.UseSwagger();
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "Generated API V1");
            c.RoutePrefix = string.Empty; // Serve Swagger UI at the app's root
        });
    }

    app.UseHttpsRedirection();
    app.UseRouting();
    app.UseAuthorization();
    app.MapControllers();

    Log.Information("Web application configured and ready to start");
    app.Run();
}
catch (Exception ex)
{
    Log.Fatal(ex, "Application terminated unexpectedly");
}
finally
{
    Log.Information("Shutting down web application");
    Log.CloseAndFlush();
}