Clear        


                
                    // Importing required namespaces for working with Users, authentication, EF Core, JWT, and Swagger
using Users.APP;
using Users.APP.Domain;
using Users.APP.Features;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;

var builder = WebApplication.CreateBuilder(args);

// Adds service defaults like configuration, health checks, telemetry, etc.
// This is a helper method often defined in .NET template apps or extensions.
builder.AddServiceDefaults();



// ======================================================
// DATABASE CONFIGURATION
// ======================================================

// Fetch the connection string named "UsersDb" from appsettings.json or environment variables.
// This determines where the application stores and retrieves user-related data.
var connectionString = builder.Configuration.GetConnectionString("UsersDb");

// Register the UsersDb context for Entity Framework Core using SQL Server.
// This enables the app to interact with the Users database via LINQ and EF models.
//builder.Services.AddDbContext<UsersDb>(options => options.UseSqlServer(connectionString));

// Alternative: Uncomment to use SQLite instead of SQL Server
builder.Services.AddDbContext<UsersDb>(options => options.UseSqlite(connectionString));



// ======================================================
// MEDIATR CONFIGURATION
// ======================================================

// Register MediatR services from the assembly containing UsersDbHandler.
// This enables decoupled request/response logic using IRequest<T> and IRequestHandler<TRequest, TResponse>.
builder.Services.AddMediatR(config => config.RegisterServicesFromAssembly(typeof(UsersDbHandler).Assembly));



// ======================================================
// APP SETTINGS
// ======================================================

// Access the "AppSettings" section from appsettings.json.
// This section typically holds values like JWT issuer, audience, key, expiration, etc.
var section = builder.Configuration.GetSection(nameof(AppSettings));

// Bind the configuration section directly to the static AppSettings class.
// This sets values like Issuer, Audience, SecurityKey used in token creation and validation.
section.Bind(new AppSettings());



// ======================================================
// AUTHENTICATION
// ======================================================

// Enable JWT Bearer authentication as the default scheme.
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(config =>
    {
        // Define rules for validating JWT tokens.
        config.TokenValidationParameters = new TokenValidationParameters
        {
            // Match the token's issuer to the expected issuer from AppSettings.
            ValidIssuer = AppSettings.Issuer,

            // Match the token's audience to the expected audience.
            ValidAudience = AppSettings.Audience,

            // Use the symmetric key defined in AppSettings to verify the token's signature.
            IssuerSigningKey = AppSettings.SigningKey,

            // These flags ensure thorough validation of the token.
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true
        };
    });



// ======================================================
// CONTROLLERS CONFIGURATION
// ======================================================

// Register controller services so that they can handle incoming HTTP requests.
builder.Services.AddControllers();

// Enables API explorer so endpoints can be discovered.
builder.Services.AddEndpointsApiExplorer();



// ======================================================
// SWAGGER
// ======================================================

// Configure Swagger/OpenAPI documentation, including JWT auth support in the UI.
builder.Services.AddSwaggerGen(c =>
{
    // Define the basic information for your API.
    c.SwaggerDoc("v1", new OpenApiInfo
    {
        Title = "API",
        Version = "v1"
    });

    // Add the JWT Bearer scheme to the Swagger UI so tokens can be tested in requests.
    c.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, new OpenApiSecurityScheme
    {
        Name = "Authorization",
        Type = SecuritySchemeType.ApiKey,
        Scheme = JwtBearerDefaults.AuthenticationScheme,
        BearerFormat = "JWT",
        In = ParameterLocation.Header,
        Description = """
        JWT Authorization header using the Bearer scheme.
        Enter your token as: Bearer your_token_here
        Example: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
        """
    });

    // Add the security requirement globally so all endpoints are secured unless specified otherwise.
    c.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type = ReferenceType.SecurityScheme,
                    Id = JwtBearerDefaults.AuthenticationScheme
                }
            },
            Array.Empty<string>()
        }
    });
});



// ======================================================
// APPLICATION BUILD AND MIDDLEWARE PIPELINE
// ======================================================

// Build the configured application.
var app = builder.Build();

// Map default endpoints (if defined in service defaults or extensions)
app.MapDefaultEndpoints();

// Use Swagger and Swagger UI only in development for API documentation and testing.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

// Redirect HTTP requests to HTTPS for security.
app.UseHttpsRedirection();



// ======================================================
// AUTHENTICATION
// ======================================================

// Enable authentication middleware so that [Authorize] works.
app.UseAuthentication();



// Enable authorization middleware to enforce roles and permissions.
app.UseAuthorization();

// Map attribute-based controllers to routes (e.g., [Route], [HttpGet], etc.)
app.MapControllers();

// Start the application and begin processing requests.
app.Run();