using FoodsharingSiegen.Contracts.Model;
using FoodsharingSiegen.Server.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration.Json;

namespace FoodsharingSiegen.Server
{
    public static class Extensions
    {
        #region Public Method AddDatabaseContext

        /// <summary>
        ///     Configures the application's data access layer by setting up and registering a database context using SQLite.
        ///     Ensures the database file is stored within the application's base directory under a "data" folder.
        /// </summary>
        /// <param name="builder">An instance of <see cref="WebApplicationBuilder" /> used to configure the application's services and resources.</param>
        public static void AddDatabaseContext(this WebApplicationBuilder builder)
        {
            var dataDirectory = Path.Combine(AppContext.BaseDirectory, "data");
            if (!Directory.Exists(dataDirectory)) Directory.CreateDirectory(dataDirectory);

            var dbPath = Path.Combine(dataDirectory, "app.db");
            var connectionString = $"Data Source={dbPath}";

            builder.Services.AddDbContextFactory<FsContext>(options =>
                options.UseSqlite(connectionString));
        }

        #endregion

        /// <summary>
        /// Ensures that all pending database migrations are applied at runtime.
        /// This method checks for pending migrations in the database context and applies them,
        /// allowing the application to remain compatible with the latest schema changes.
        /// </summary>
        /// <param name="app">An instance of <see cref="WebApplication" /> used to access application services and lifecycle methods.</param>
        public static void ApplyMigrations(this WebApplication app)
        {
            using var scope = app.Services.CreateScope();
            var dbContext = scope.ServiceProvider.GetRequiredService<FsContext>();

            // Check and apply pending migrations
            var pendingMigrations = dbContext.Database.GetPendingMigrations();
            if (pendingMigrations.Any())
            {
                Console.WriteLine("Applying pending migrations...");
                dbContext.Database.Migrate();
                Console.WriteLine("Migrations applied successfully.");
            }
            else
            {
                Console.WriteLine("No pending migrations found.");
            }
        }

        #region Public Method LoadAppSettings

        /// <summary>
        ///     Loads application settings from JSON configuration files located in a designated "config" directory.
        ///     Clears existing JSON configuration files and ensures settings from the specified files are applied.
        /// </summary>
        /// <param name="builder">An instance of <see cref="WebApplicationBuilder" /> used to configure and load application settings.</param>
        public static void LoadAppSettings(this WebApplicationBuilder builder)
        {
            // Clear loaded json files
            foreach (var configurationSource in builder.Configuration.Sources.Where(x => x is JsonConfigurationSource).ToList())
                builder.Configuration.Sources.Remove(configurationSource);

            // Define the directory where your appsettings files reside
            var configDir = Path.Combine(builder.Environment.ContentRootPath, "config");

            // Check if the directory exists
            if (Directory.Exists(configDir))
            {
                // Get all JSON files that start with "appsettings" in the directory and its subdirectories
                var configFiles = Directory.EnumerateFiles(configDir, "appsettings*.json", SearchOption.AllDirectories);

                // Add each file to the configuration
                foreach (var file in configFiles) builder.Configuration.AddJsonFile(file, true, true);
            }
            
            builder.Services.Configure<AppSettings>(builder.Configuration.GetSection("Settings"));
        }

        #endregion
    }
}