Clear        


                
                    using APP.Authentication.Services;
using APP.Domain;
using APP.Models;
using APP.Services;
using CORE.Authentication.Services;
using CORE.Services;
using CORE.Session.Services;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.EntityFrameworkCore;

// Create a builder for the web application and initialize
// configuration, logging, etc.
var builder = WebApplication.CreateBuilder(args);



// --------------------------------------------------------
// Add services to the IoC (Inversion of Control) container
// for Dependency Injections.
// --------------------------------------------------------
// Register the application's DbContext dependency
// injection by sending Db instances to the injected service
// class constructors' DbContext or Db parameter, using SQLite
// with the connection string from appsettings.json.
builder.Services.AddDbContext<DbContext, Db>(
    options => options.UseSqlite(
        builder.Configuration.GetConnectionString(nameof(Db))));
// nameof(Db) = "Db" which is the class name.

// Register the UserService dependency injection by sending
// IService<UserRequest, UserResponse> instance reference to
// the injected controller class constructor's
// IService<UserRequest, UserResponse> parameter.
// Injection through abstract class or interface is suitable
// for SOLID Principles.
builder.Services
    .AddScoped<IService<UserRequest, UserResponse>, UserService>();

// Register the RoleService dependency injection by sending
// IService<RoleRequest, RoleResponse> instance reference to
// the injected controller class constructor's
// IService<RoleRequest, RoleResponse> parameter.
builder.Services
    .AddScoped<IService<RoleRequest, RoleResponse>, RoleService>();

// Register the StatusService dependency injection by sending
// IService<StatusRequest, StatusResponse> instance reference to
// the injected controller class constructor's
// IService<StatusRequest, StatusResponse> parameter.
builder.Services
    .AddScoped<IService<StatusRequest, StatusResponse>, StatusService>();



// --------------------------
// Authentication and Session
// --------------------------
// Register IHttpContextAccessor as a singleton service.
// Enables access to the current HttpContext from classes other than
// controller classes such as services.
// Required for services like CookieAuthService that need to read
// or modify HTTP context (e.g., authentication, user info).
// Allows constructor injection of IHttpContextAccessor throughout
// the services of the application.
builder.Services.AddHttpContextAccessor();



// --------------
// Authentication
// --------------
// Register CookieAuthService as a scoped dependency for ICookieAuthService.
// Scoped lifetime ensures a new instance per HTTP request, which is
// required for services accessing HttpContext.
// CookieAuthService handles user authentication using cookies, supporting
// sign in and sign out operations.
// This service registration enables constructor injection of
// ICookieAuthService to the controllers or services throughout the application.
builder.Services.AddScoped<ICookieAuthService, CookieAuthService>();



// --------------
// Authentication
// --------------
// Register AuthService as a scoped dependency for IAuthService.
// Scoped lifetime ensures a new instance per HTTP request, which is
// required for services accessing HttpContext.
// AuthService handles user authentication using injected ICookieAuthService
// instance, supporting log in, log out and register operations.
// This service registration enables constructor injection of
// IAuthService to the controllers or services throughout the application.
builder.Services.AddScoped<IAuthService, AuthService>();



// --------------
// Authentication
// --------------
// Configure authentication services using cookie-based authentication.
// - Sets the default authentication scheme to Cookies.
// - Specifies options for cookie authentication:
//   - LoginPath: Path to redirect unauthenticated users
//     (when authentication is required).
//   - AccessDeniedPath: Path to redirect users who are authenticated
//     but lack required permissions.
//   - ExpireTimeSpan: Duration before the authentication cookie expires
//     (here, 1 hour).
//   - SlidingExpiration: Resets the expiration time on each request
//     to keep active sessions alive.
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
    {
        options.LoginPath = "/Login"; 
        // changed from /Auth/Login to /Login since route will be changed for action
        options.AccessDeniedPath = "/Login"; 
        // changed from /Auth/Login to /Login since route will be changed for action
        options.ExpireTimeSpan = TimeSpan.FromHours(1);
        options.SlidingExpiration = true;
    });



// -------
// Session
// -------
// Register session services and configure session options.
// Sets the session idle timeout to 30 minutes (default 20 minutes);
// if no activity occurs within this period, the session expires.
// Enables storing user-specific data (e.g., shopping cart, temporary users)
// across multiple requests during the session lifetime.
// Required for features that rely on session state, such as
// UserSessionService and SessionService.
builder.Services.AddSession(config =>
{
    config.IdleTimeout = TimeSpan.FromMinutes(30);
});



// -------
// Session
// -------
// Register the concrete SessionService as a scoped dependency.
// Concrete classes can also be used for registration, but using an
// abstract base class or interface allows for more flexible
// dependency injection and testing (Also better for SOLID Principles).
// Since session operations are standard and are not expected to change,
// concrete class injection is implemented.
// Scoped lifetime ensures a new instance per HTTP request,
// which is required for services accessing HttpContext.
// SessionService handles session management.
// This service registration enables constructor injection of SessionService
// to the controllers or services throughout the application.
builder.Services.AddScoped<SessionService>();



// -------
// Session
// -------
// Register the concrete UserSessionService as a scoped dependency.
// Scoped lifetime ensures a new instance per HTTP request.
// UserSessionService handles temporary users management.
// This service registration enables constructor injection of UserSessionService
// to the controllers or services throughout the application.
builder.Services.AddScoped<UserSessionService>();



// Add support for controllers and views (MVC pattern).
builder.Services.AddControllersWithViews();

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

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    // Use a custom error handler in non-development environments
    // redirecting to Home controller's Error action.
    app.UseExceptionHandler("/Home/Error");

    // Enable HTTP Strict Transport Security (HSTS).
    // The default HSTS value is 30 days. You may want to change this
    // for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

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

// Enable serving static files (e.g., HTML, CSS, JS, images).
app.UseStaticFiles();

// Enable routing capabilities.
app.UseRouting();



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



// Enable authorization middleware.
app.UseAuthorization();



// -------
// Session
// -------
// Enable session middleware in the HTTP request pipeline.
app.UseSession();



// Configure the default route for controllers for sending requests
// to controllers' actions as
// controller/action/id where id is optional.
app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

// Start the application and listen for incoming HTTP requests.
app.Run();