using Serilog;
using Serilog.Ui.Core.Extensions;
using Serilog.Ui.SqliteDataProvider.Extensions;
using Serilog.Ui.Web.Extensions;
using Scalar.AspNetCore;
using DocumentOperator.Infrastructure.Configuration;
using DocumentOperator.Application;
using DocumentOperator.Application.Common.Configuration;
using DocumentOperator.Infrastructure;
using DocumentOperator.API.Middleware;
using DocumentOperator.API.Configuration;

var builder = WebApplication.CreateBuilder(args);

// ========================================
// 1. Serilog Configuration
// ========================================
Log.Logger = new LoggerConfiguration()
    .ReadFrom.Configuration(builder.Configuration)
    .Enrich.FromLogContext()
    .Enrich.WithProperty("Application", "DocumentOperator")
    .CreateLogger();

builder.Host.UseSerilog();

Log.Information("Starting DocumentOperator API...");

try
{
    // ========================================
    // 2. Options Pattern Configuration
    // ========================================
    builder.Services.Configure<DocumentOperatorSettings>(
        builder.Configuration.GetSection(DocumentOperatorSettings.SectionName));

    builder.Services.Configure<ZugferdSettings>(
        builder.Configuration.GetSection("ZugferdSettings"));

    builder.Services.Configure<RedisSettings>(
        builder.Configuration.GetSection(RedisSettings.SectionName));

    builder.Services.Configure<ApiKeySettings>(
        builder.Configuration.GetSection(ApiKeySettings.SectionName));

    builder.Services.Configure<SwaggerSettings>(
        builder.Configuration.GetSection(SwaggerSettings.SectionName));

    // ========================================
    // 3. Services (Clean Architecture Layers)
    // ========================================
    builder.Services.AddApplication(builder.Configuration);      // Application Layer (MediatR, FluentValidation, Behaviors)
    builder.Services.AddInfrastructure();   // Infrastructure Layer (DevExpress, Services)

    builder.Services.AddControllers();      // Controllers (Controller-based API)
    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerDocumentation(builder.Configuration);

    // ========================================
    // 4. Serilog.UI Configuration
    // ========================================
    var logDirectory = builder.Configuration.GetValue<string>("Application:LogDirectory")
        ?? throw new InvalidOperationException("Application:LogDirectory not found in configuration.");
    var sqliteDbPath = Path.Combine(logDirectory, "logs.db");

    builder.Services.AddSerilogUi(logUIOpt =>
    {
        logUIOpt.UseSqliteServer(dbOpt =>
        {
            dbOpt.WithConnectionString($"Data Source={sqliteDbPath}");
            dbOpt.WithTable("Logs");
        });
    });

    // ========================================
    // 5. Build App
    // ========================================
    var app = builder.Build();

    // ========================================
    // 5. Middleware Pipeline (Order matters!)
    // ========================================

    // Exception Handling FIRST (catches all exceptions from subsequent middleware)
    app.UseMiddleware<ExceptionHandlingMiddleware>();

    // ========================================
    // Swagger/OpenAPI (Conditional based on settings)
    // ========================================
    var swaggerSettings = builder.Configuration.GetSection(SwaggerSettings.SectionName).Get<SwaggerSettings>()
        ?? new SwaggerSettings();

    if (app.Environment.IsDevelopment() || swaggerSettings.EnableInProduction)
    {
        app.UseSwagger();
        
        // Swagger UI (classic)
        app.UseSwaggerUI(options =>
        {
            options.SwaggerEndpoint($"/swagger/{swaggerSettings.Version}/swagger.json", 
                $"{swaggerSettings.Title} {swaggerSettings.Version}");
            options.RoutePrefix = "swagger"; // /swagger
        });

        // Scalar UI (modern alternative)
        app.MapScalarApiReference(options =>
        {
            options
                .WithTitle(swaggerSettings.Title)
                .WithTheme(ScalarTheme.DeepSpace)
                .WithDefaultHttpClient(ScalarTarget.CSharp, ScalarClient.HttpClient);
        });
    }

    app.UseSerilogRequestLogging(); // Log HTTP Requests

    app.UseHttpsRedirection();

    // ========================================
    // 6. Serilog.UI Dashboard
    // ========================================
    app.UseSerilogUi(); // Accessible at /serilog-ui

    // ========================================
    // 7. Endpoints (Controller-based API)
    // ========================================
    app.MapControllers(); // Maps all [ApiController] controllers

    Log.Information("DocumentOperator API started successfully");

    app.Run();
}
catch (Exception ex)
{
    Log.Fatal(ex, "Application startup failed");
    throw;
}
finally
{
    Log.CloseAndFlush();
}

// Make Program class accessible for Integration Tests
/// <summary>
/// Entry point class for the DocumentOperator API.
/// Made partial and public for integration test access.
/// </summary>
public partial class Program { }