using GermanApp.Application.DTOs; using GermanApp.Application.UseCases.Commands; using GermanApp.Domain.Interfaces; using GermanApp.Infrastructure.Data.DbContext; using GermanApp.Infrastructure.Data.Repositories; using GermanApp.Infrastructure.Data.SeedData; using GermanApp.Presentation.Endpoints; using GermanApp.Shared.Middleware; using Microsoft.EntityFrameworkCore; using Serilog; // Configure Serilog Log.Logger = new LoggerConfiguration() .MinimumLevel.Debug() .WriteTo.Console() .CreateBootstrapLogger(); try { var builder = WebApplication.CreateBuilder(args); // Add Serilog to the builder builder.Host.UseSerilog((ctx, lc) => lc .MinimumLevel.Debug() .WriteTo.Console() .ReadFrom.Configuration(ctx.Configuration)); // ============================================ // PRESENTATION LAYER - API Configuration // ============================================ // Add services to the container. builder.Services.AddOpenApi(); // Add Health Checks builder.Services.AddHealthChecks() .AddDbContextCheck(); // Configure CORS builder.Services.AddCors(options => { options.AddPolicy("AllowAll", builder => { builder.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader(); }); }); // Add services for Minimal APIs builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); // ============================================ // INFRASTRUCTURE LAYER - Database & External Services // ============================================ // Add DbContext with PostgreSQL builder.Services.AddDbContext(options => { // Using PostgreSQL for production and development options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection") ?? "Host=localhost;Port=5432;Database=DeutschLernen;Username=postgres;Password=postgres"); // Enable sensitive data logging in development if (builder.Environment.IsDevelopment()) { options.EnableSensitiveDataLogging(); options.EnableDetailedErrors(); } }); // Register repositories (Infrastructure implementations of Domain interfaces) builder.Services.AddScoped(); // ============================================ // APPLICATION LAYER - Use Cases & Services // ============================================ // Register command handlers builder.Services.AddScoped, CreateLessonCommandHandler>(); var app = builder.Build(); // Configure the HTTP request pipeline. // Use exception middleware first (to catch all exceptions) app.UseExceptionMiddleware(); if (app.Environment.IsDevelopment()) { app.MapOpenApi(); app.UseSwagger(); app.UseSwaggerUI(); } // Use CORS app.UseCors("AllowAll"); // Use Health Checks app.MapHealthChecks("/health"); // Seed database with initial data app.SeedDatabase(); // Map Clean Architecture endpoints app.MapLessonsEndpoints(); // Keep original WeatherForecast endpoint for reference app.MapGet("/weatherforecast", () => { var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; var forecast = Enumerable.Range(1, 5).Select(index => new WeatherForecast ( DateOnly.FromDateTime(DateTime.Now.AddDays(index)), Random.Shared.Next(-20, 55), summaries[Random.Shared.Next(summaries.Length)] )) .ToArray(); return forecast; }) .WithName("GetWeatherForecast"); app.Run(); } catch (Exception ex) { Log.Fatal(ex, "Application terminated unexpectedly"); } finally { Log.CloseAndFlush(); } // Existing record for reference record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary) { public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); }